package com.test.practice.java8.lambda;

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Lambda
 *
 * @author: Jovi
 * <p>
 * 本人认为是进一步简化lambda表达式的声明的一种语法糖。
 * <p>
 * 前面的例子中已有使用到： execStrs.forEach(System.out::println);
 * <p>
 * 2.1方法引用
 * objectName::instanceMethod
 * <p>
 * ClassName::staticMethod
 * <p>
 * ClassName::instanceMethod
 * <p>
 * 前两种方式类似，等同于把lambda表达式的参数直接当成instanceMethod|staticMethod的参数来调用。
 * 比如System.out::println等同于x->System.out.println(x)；Math::max等同于(x, y)->Math.max(x,y)。
 * <p>
 * 最后一种方式，等同于把lambda表达式的第一个参数当成instanceMethod的目标对象，其他剩余参数当成该方法的参数。
 * 比如String::toLowerCase等同于x->x.toLowerCase()。
 * <p>
 * 可以这么理解，前两种是将传入对象当参数执行方法，后一种是调用传入对象的方法。
 * <p>
 * 2.2构造器引用
 * 构造器引用语法如下：ClassName::new，把lambda表达式的参数当成ClassName构造器的参数 。例如BigDecimal::new等同于x->new BigDecimal(x)。
 * @createTime: 2018/3/2 下午4:25
 **/
public class Lambda {

    private String round;

    public String getRound() {
        return round;
    }

    public void setRound(String round) {
        this.round = round;
    }

    /**
     * @param round
     */
    public Lambda(String round) {
        this.round = round;
    }

    public Lambda() {
    }

    private static void base() {
        Lambda l1 = new Lambda("3");
        Lambda l2 = new Lambda("2");
        Lambda l3 = new Lambda("1");

        List<Lambda> list = new ArrayList<Lambda>();

        list.add(l1);
        list.add(l2);
        list.add(l3);

        list.forEach(c -> System.out.println(c.getRound()));

        list.sort((o1, o2) -> o1.getRound().compareTo(o2.getRound()));

        list.forEach(a -> System.out.println(a.getRound()));

        list.forEach(System.out::println);

        System.out.println("nihao");
    }


    private void thisObject() {
        List<String> proStrs = Arrays.asList(new String[]{"NI", "HAO", "LAMBDA"});

        List<String> execStrs = proStrs.stream().map(str -> {
            System.out.println(this.getClass().getName());//this不是指向lambda表达式产生的那个SAM对象，而是声明它的外部对象。
            return str.toLowerCase();
        }).collect(Collectors.toList());

        execStrs.forEach(System.out::println);
    }

    private static void variable() {
        String waibu = "lambda:";

        List<String> proStrs = Arrays.asList(new String[]{"NI", "HAO", "LAMBDA"});

        List<String> execStrs = proStrs.stream().map(chuandi -> {

            // waibu = "nihao"; lambda表达式访问外部变量有一个非常重要的限制：变量不可变（只是引用不可变，而不是真正的不可变）

            Long neibuzidingyi = System.currentTimeMillis();

            return waibu + chuandi + "-----:" + neibuzidingyi;

        }).collect(Collectors.toList());

        execStrs.forEach(System.out::println);
    }

    public static void main(String[] args) {


//        List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
//        System.out.println("sum is:" + nums.stream().filter(num -> num != null).distinct()
//                .mapToInt(num -> num * 2).peek(System.out::println).skip(2).limit(4).sum());


//        variable();

        base();

//        new Lambda().thisObject();

    }

}
